package com.zl.learning.collection;

import org.junit.Test;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class HashMapTest {
    @Test
    public void test1() {
        Map<String, Object> map = MapBuilder.<String, Object>newHashMap("name", "zhangsan").build("age", 14).builder();
        map.forEach((k, v) -> System.out.println(k + "---" + v));
    }

    ConcurrentHashMap<String, Set<String>> t1 = new ConcurrentHashMap<>(20);
    ConcurrentHashMap<String, Set<String>> t2 = new ConcurrentHashMap<>(20);
    ConcurrentHashMap<String, Set<String>> t3;

    @Test
    public void test2() {


        Set<String> ts1 = t1.computeIfAbsent("a", k -> new HashSet<>());
        ts1.add("a1");
        ts1.add("a2");
        ts1.add("a3");
        Set<String> ts2 = t1.computeIfAbsent("b", k -> new HashSet<>());
        ts2.add("b1");
        ts2.add("b2");
        ts2.add("b3");
        swap();
        System.out.println(t1);
        System.out.println(t2);
        System.out.println(t3);
        System.out.println(t1 == t3);
        System.out.println(t1 == t2);
        swap();
        System.out.println(t1);
        System.out.println(t2);
        System.out.println(t3);
        System.out.println(t1 == t3);
        System.out.println(t1 == t2);
        swap();
        System.out.println(t1);
        System.out.println(t2);
        System.out.println(t3);
        System.out.println(t1 == t3);
        System.out.println(t1 == t2);
    }

    private void swap() {
        t3 = t2;
        t2 = t1;
        t1 = t3;
        System.out.println("------------------");
    }

    /**
     * compute：V compute(K key, BiFunction < ? super K, ? super V, ? extends V> remappingFunction)
     * <p>
     * compute的方法,指定的key在map中的值进行操作 不管存不存在，操作完成后保存到map中
     */
    @Test
    public void testCompute() {
        HashMap<String, Integer> map = new HashMap<>();
        map.compute("3", (k, v) -> v == null ? 0 : v + 1);
        map.compute("3", (k, v) -> v == null ? 0 : v + 1);
        Integer integer = map.compute("3", (k, v) -> v == null ? 0 : v + 1);

        System.out.println(integer);
        System.out.println(map.toString());
    }

    /**
     * computeIfAbsent(K key, Function《? super K, ? extends V> mappingFunction)
     * <p>
     * computeIfAbsent的方法有两个参数 第一个是所选map的key，第二个是需要做的操作。这个方法当key值不存在时才起作用。
     * <p>
     * 当key存在返回当前value值，不存在执行函数并保存到map中
     */
    @Test
    public void testComputeIfAbsent() {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("1", 1);
        map.put("2", 2);
        map.put("3", 3);
        Integer integer = map.computeIfAbsent("3", key -> 4);//key存在返回value
        Integer integer1 = map.computeIfAbsent("4", key -> 4);//key不存在执行函数存入
        Integer integer2 = map.computeIfAbsent("4", key -> 4);//key不存在执行函数存入
        System.out.println(integer);
        System.out.println(integer1);
        System.out.println(integer2);
        System.out.println(map.toString());
    }

    /**
     * computeIfPresent：V computeIfPresent(K key, BiFunction < ? super K, ? super V, ? extends V> remappingFunction)
     * <p>
     * computeIfPresent 的方法,对 指定的 在map中已经存在的key的value进行操作。只对已经存在key的进行操作，其他不操作
     */
    @Test
    public void testComputeIfPresent() {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("1", 1);
        map.put("2", 2);
        map.put("3", 3);
        //只对map中存在的key对应的value进行操作
        Integer integer = map.computeIfPresent("3", (k, v) -> v + 1);
        Integer integer1 = map.computeIfPresent("4", (k, v) -> v + 1);
        System.out.println(integer);
        System.out.println(integer1);
        System.out.println(map.toString());
    }

    @Test
    public void testMerge() {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("1", 1);
        map.put("2", 2);
        map.put("3", 3);
        //只对map中存在的key对应的value进行操作
        Integer integer = map.merge("3", 1, Integer::sum);
        Integer integer1 = map.merge("4", 1, Integer::sum);
        System.out.println(integer);
        System.out.println(integer1);
        System.out.println(map.toString());
    }

    @Test
    public void test3() {
        ConcurrentHashMap<String, CopyOnWriteArraySet<String>> userMap = new ConcurrentHashMap<>();
        userMap.computeIfAbsent("a", key -> new CopyOnWriteArraySet<>()).add("cccc");
        userMap.computeIfAbsent("b", key -> new CopyOnWriteArraySet<>()).add("dddd");
        CopyOnWriteArraySet<String> set = userMap.computeIfAbsent("a", key -> new CopyOnWriteArraySet<>());
        System.out.println(set);
        set.add("aaaa");
        set = userMap.computeIfAbsent("a", key -> new CopyOnWriteArraySet<>());
        System.out.println(set);
        userMap.computeIfPresent("b", (key, val) -> {
            val.remove("dddd");
            userMap.remove(key);
            return val;
        });
        System.out.println(userMap.get("b"));
    }

    @Test
    public void test4() {
        ConcurrentHashMap<String, CopyOnWriteArraySet<String>> userMap = new ConcurrentHashMap<>();
        userMap.computeIfAbsent("a", key -> new CopyOnWriteArraySet<>()).add("cccc");
        userMap.computeIfAbsent("a", key -> new CopyOnWriteArraySet<>()).add("dddd");
        ConcurrentHashMap<String, User> sessionMap = new ConcurrentHashMap<>();
        sessionMap.put("cc", new User("a", "zhangsan"));
        Optional.ofNullable(sessionMap.get("cccc")).map(User::getUserId).map(userMap::get).ifPresent(r -> r.remove("cccc"));
        System.out.println(userMap);
    }

    @Test
    public void test5() {
        User[] users = {new User("a", "aa"), new User("b", "bb"), new User("c", "cc")};
//        String name = Optional.of(users).flatMap(r -> Stream.of(r).filter(c -> c.getUserId().equals("w")).findAny().map(User::getUsername)).orElse("ddddd");
//        System.out.println(name);
        Map<String, User> userMap = Stream.of(users).collect(Collectors.toMap(User::getUserId, c -> c));
        userMap.remove("a");
        userMap.keySet().remove("b");
        System.out.println(userMap);
    }

    @Test
    public void test6() {
        int cap = 3;
//        cap = cap << 1;
//        cap = cap << 1;
//        cap = cap << 1;
        cap = cap >> 1;
        cap = cap >> 1;
        cap = cap >> 1;
//        System.out.println(cap);
        int n = 10;
        int hash = 780;
        int i = (n-1)& hash;
        System.out.println(i);
        HashMap<String, String> map = new HashMap<>();
        map.put("a","a");
    }
}
